package com.dmz.workflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dmz.workflow.base.BaseServiceImpl;
import com.dmz.workflow.constant.CommonConstants;
import com.dmz.workflow.constant.ProcessDefinitionConstants;
import com.dmz.workflow.dao.WorkflowNodeExtMapper;
import com.dmz.workflow.dto.OneHourAlert;
import com.dmz.workflow.service.WorkflowNodeExtService;
import com.dmz.workflow.util.ObjectUtils;
import com.echronos.workflow.constant.ProcessConstants;
import com.dmz.workflow.entity.StaffInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class WorkflowNodeExtServiceImpl extends BaseServiceImpl<WorkflowNodeExtMapper, StaffInfo> implements WorkflowNodeExtService {

    @Autowired
    private WorkflowNodeExtMapper workflowNodeExtMapper;

    private LambdaUpdateWrapper<StaffInfo> lambdaUpdateWrapper;

    @Override
    public List<StaffInfo> selectListByProcessInstanceIdAndNodeType(String processInstanceId, String nodeType) {
        LambdaQueryWrapper<StaffInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StaffInfo::getProcessInstanceId, processInstanceId)
                .eq(StaffInfo::getIsDeleted, CommonConstants.DATA_NOT_DELETED_STATUS);
        if (StringUtils.isNotEmpty(nodeType)) {
            lambdaQueryWrapper.eq(StaffInfo::getTypeNode, nodeType);
        }
        return workflowNodeExtMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public StaffInfo selectPersonalNode(StaffInfo staffInfo) {
        LambdaQueryWrapper<StaffInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StaffInfo::getProcessInstanceId, staffInfo.getProcessInstanceId())
                .eq(StaffInfo::getIdNode, staffInfo.getIdNode())
                .eq(StaffInfo::getMemberId, staffInfo.getMemberId());
        return workflowNodeExtMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public int updateNodeExtByProcessInstanceIdAndNodeId(StaffInfo staffInfo) {
        lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StaffInfo::getProcessInstanceId, staffInfo.getProcessInstanceId());
        if (ObjectUtils.isNotEmpty(staffInfo.getMemberId())) {
            lambdaUpdateWrapper.eq(StaffInfo::getMemberId, staffInfo.getMemberId());
        }
        if (StringUtils.isNotEmpty(staffInfo.getTypeNode())) {
            lambdaUpdateWrapper.eq(StaffInfo::getTypeNode, staffInfo.getTypeNode());
        }
        if (StringUtils.isNotEmpty(staffInfo.getIdNode())) {
            lambdaUpdateWrapper.eq(StaffInfo::getIdNode, staffInfo.getIdNode());
        }
        return workflowNodeExtMapper.update(staffInfo, lambdaUpdateWrapper);
    }

    @Override
    public int updateNodeExtCaseRefuseOperation(String processInstanceId) {
        lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StaffInfo::getProcessInstanceId, processInstanceId)
                .eq(StaffInfo::getStatus, ProcessConstants.PERSON_APPROVING_STATUS);
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setIsDeleted(CommonConstants.DATA_DELETED_STATUS);
        return workflowNodeExtMapper.update(staffInfo, lambdaUpdateWrapper);
    }

    @Override
    public IPage<StaffInfo> selectDuplicatePage(String memberId, Integer pageSize, Integer pageNum, String keyword, Boolean isUnread, String nodeType) {
        LambdaQueryWrapper<StaffInfo> lambdaQueryWrapper = null;
        if (ProcessDefinitionConstants.CHECK_NODE.equals(nodeType)) {
            QueryWrapper<StaffInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("distinct process_instance_id");
            lambdaQueryWrapper = queryWrapper.lambda();
            lambdaQueryWrapper.ne(StaffInfo::getIdNode, ProcessDefinitionConstants.START_NODE_NAME);
            List<Integer> statusList = new ArrayList<>();
            statusList.add(ProcessConstants.PERSON_APPROVED_STATUS);
            statusList.add(ProcessConstants.PERSON_REFUSE_STATUS);
            statusList.add(ProcessConstants.PERSON_DELEGATE_STATUS);
            statusList.add(ProcessConstants.PERSON_TRANSFER_STATUS);
            statusList.add(ProcessConstants.PERSON_REJECT_STATUS);
            statusList.add(ProcessConstants.PERSON_ADD_BACK_SIGN_STATUS);
            statusList.add(ProcessConstants.PERSON_ADD_FRONT_SIGN_STATUS);
            lambdaQueryWrapper.in(StaffInfo::getStatus, statusList)
                    .in(StaffInfo::getTypeNode, nodeType, ProcessDefinitionConstants.BACK_NODE);
        }
        if (ProcessDefinitionConstants.DUPLICATE_NODE.equals(nodeType)) {
            lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StaffInfo::getStatus, ProcessConstants.PERSON_APPROVED_STATUS)
                    .eq(StaffInfo::getTypeNode, nodeType);
        }
        if (ObjectUtils.isNotEmpty(isUnread) && isUnread) {
            lambdaQueryWrapper.eq(StaffInfo::getReadStatus, 0);
        }
        lambdaQueryWrapper.eq(StaffInfo::getMemberId, memberId);
        if (StringUtils.isNotEmpty(keyword)) {
            lambdaQueryWrapper.and(wrapper -> wrapper.like(ObjectUtils.isNotEmpty(keyword), StaffInfo::getProcessName, keyword)
                    .or()
                    .like(ObjectUtils.isNotEmpty(keyword), StaffInfo::getStarterName, keyword));
        }
        lambdaQueryWrapper.orderByDesc(StaffInfo::getCreateTime);
        IPage<StaffInfo> staffInfoIPage = new Page<>(pageNum + 1, pageSize);
        return workflowNodeExtMapper.selectPage(staffInfoIPage, lambdaQueryWrapper);
    }

    @Override
    public int updateCcReadStatusByStatus(String[] processInstanceIds, Integer memberId) {
        lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.in(StaffInfo::getProcessInstanceId, processInstanceIds)
                .eq(StaffInfo::getMemberId, memberId)
                .eq(StaffInfo::getTypeNode, ProcessDefinitionConstants.DUPLICATE_NODE);
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setReadStatus(CommonConstants.CC_APPROVAL_READ_STATUS);
        return workflowNodeExtMapper.update(staffInfo, lambdaUpdateWrapper);
    }

    @Override
    public int markAllRead(Integer memberId) {
        lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StaffInfo::getTypeNode, ProcessDefinitionConstants.DUPLICATE_NODE)
                .eq(StaffInfo::getMemberId, memberId)
                .eq(StaffInfo::getStatus, ProcessConstants.PERSON_APPROVED_STATUS);
        StaffInfo staffInfo = new StaffInfo();
        staffInfo.setReadStatus(CommonConstants.CC_APPROVAL_READ_STATUS);
        return workflowNodeExtMapper.update(staffInfo, lambdaUpdateWrapper);
    }

    @Override
    public int updateBatchTaskId(List<StaffInfo> staffInfos) {
        return workflowNodeExtMapper.updateBatchTaskId(staffInfos);
    }

    @Override
    public List<StaffInfo> selectListByProcessInstanceIdAndNodeId(String processInstanceId, List<String> nodeIds) {
        LambdaQueryWrapper<StaffInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StaffInfo::getProcessInstanceId, processInstanceId)
                .eq(StaffInfo::getIsDeleted, CommonConstants.DATA_NOT_DELETED_STATUS)
                .in(StaffInfo::getIdNode, nodeIds);
        return workflowNodeExtMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public List<OneHourAlert> selectStaffListToInformToApprove() {
        return workflowNodeExtMapper.selectStaffListToInformToApprove();
    }

    @Override
    public List<Object> selectProcessInvolvedMembers(String processInstanceId) {
        QueryWrapper<StaffInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("distinct member_id").lambda().eq(StaffInfo::getProcessInstanceId, processInstanceId);
        return workflowNodeExtMapper.selectObjs(queryWrapper);
    }

    @Override
    public StaffInfo selectPersonalNodeApprovingNum(StaffInfo staffInfo) {
        LambdaQueryWrapper<StaffInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StaffInfo::getProcessInstanceId, staffInfo.getProcessInstanceId())
                .eq(StaffInfo::getIdNode, staffInfo.getIdNode())
                .eq(StaffInfo::getMemberId, staffInfo.getMemberId())
                .eq(StaffInfo::getStatus, staffInfo.getStatus());
        return workflowNodeExtMapper.selectOne(lambdaQueryWrapper);
    }
}
